package com.heatup.apt.api.service.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.plugins.Page;
import com.heatup.apt.api.service.RechargeDiscountService;
import com.heatup.apt.api.service.TemplateSendService;
import com.heatup.apt.api.service.UserAccountService;
import com.heatup.apt.common.constants.CashcardConstants;
import com.heatup.apt.common.constants.OrderContants;
import com.heatup.apt.common.dao.CashcardDetailMapper;
import com.heatup.apt.common.dao.CashcardInfoMapper;
import com.heatup.apt.common.dao.OrderInfoMapper;
import com.heatup.apt.common.dao.user.UserAccountRechargeMapper;
import com.heatup.apt.common.dao.user.UserInfoMapper;
import com.heatup.apt.common.util.CouponUtil;
import com.heatup.apt.common.util.DateUtils;
import com.heatup.apt.model.CashcardDetail;
import com.heatup.apt.model.CashcardInfo;
import com.heatup.apt.model.RechargeDiscount;
import com.heatup.apt.model.api.ApiResultModel;
import com.heatup.apt.model.order.YearCardConvertDateOrderLog;
import com.heatup.apt.model.user.UserAccountRecharge;
import com.heatup.apt.model.user.UserInfo;

/**
 * @see //用户虚拟账号(储值卡业务)实现类
 *  * @author maxxiang
 *
 */
@Service("userAccountService")
public class UserAccountServiceImpl implements UserAccountService {
	private static final Logger logger = LoggerFactory.getLogger(UserAccountServiceImpl.class);
	
	@Autowired
    CashcardInfoMapper cashcardInfoMapper;
	
	@Autowired
    CashcardDetailMapper cashcardDetailMapper;
	
	@Autowired
	UserAccountRechargeMapper userAccountRechargeMapper;
	
	@Autowired
	UserInfoMapper userInfoMapper;
	
	@Autowired
    RechargeDiscountService rechargeDiscountService;
	
	@Autowired
    TemplateSendService templateSendService;
	
	@Autowired
	private OrderInfoMapper orderInfoMapper;
	
	//更新用户账号的余额数
	private BigDecimal updateUserAccountRecord(Integer userId, BigDecimal addAmt){
		if (userId<1 || addAmt.floatValue() < 0.001){
			return BigDecimal.ZERO;
		}
		UserInfo userInfo = userInfoMapper.selectById(userId);
		
		BigDecimal total = userInfo.getAccountAmt();
		if (total == null ){
			total = BigDecimal.ZERO;
		}
		
		userInfo.setAccountAmt(total.add(addAmt));  //把储值卡的金额加上去
		userInfo.setUpdatedTime(new Date());
				
		int ret = userInfoMapper.updateSelectiveById(userInfo); //把余额的增加 更新到账号中

		if (ret == 0){
			throw new RuntimeException();
		}
		
		return userInfo.getAccountAmt();
	}
	
	//插入一条记录到充值记录表
	private boolean insertUserAccountRechargeRecord(Integer userId, Integer type, BigDecimal faceAmt, BigDecimal actualAmt,String code){
		if (userId<1 || faceAmt.floatValue() < 0.001  || actualAmt.floatValue() < 0.001){
			return false;
		}
		
		UserAccountRecharge recharge = new UserAccountRecharge();
		recharge.setUserId(userId);
		recharge.setRechargeType(type);
		recharge.setFaceAmt(faceAmt);
		recharge.setActualAmt(actualAmt);
		recharge.setCreateTime(new Date());
		recharge.setChangeCode(code);
		
		int ret = userAccountRechargeMapper.insertSelective(recharge);
		if (ret == 0){
			throw new RuntimeException();
		}
		
		return true;
		
	}
	
	//添加或兑换一张优惠券， 先判断条件，再insert or update.
	private Ret_ChangeType insertOrUpdateCashcardDetailBy(CashcardInfo info, Integer userId, CashcardDetail detail, boolean bInsert,Map<String, Object> retMap, boolean onlyQuery){
		if (CashcardConstants.CashcardStatus_Online == info.getCashcardStatus()){  //2表示上架中
			if(info.getMaxCount() != 0 && info.getGetedCount() >= info.getMaxCount()){ //已领满
				return Ret_ChangeType.Ret_IsMax;
			}
			Date currDate= DateUtils.getDateShort(new Date());
			if(info.getChangeMode() == 2){//2表示限制兑换时间
				if(retMap != null){
					retMap.put("change_begin_date", DateUtils.toDateString(info.getChangeBeginDate()));
					retMap.put("change_end_date", DateUtils.toDateString(info.getChangeEndDate()));
				}

				if(currDate.before(info.getChangeBeginDate())){
					return Ret_ChangeType.Ret_BeforeTime;  //该券还未到兑换时间
				}else if (currDate.after(info.getChangeEndDate())){
					return Ret_ChangeType.Ret_ExpiredTime;  //该券的兑换时间已过
				}
			}
			
			//如果只是查询，则到此为止，后面就是直接兑换了，
			if(onlyQuery==true){
				return Ret_ChangeType.Ret_Success;
			}

			
			int isUsed = 1;			//虚拟卡是兑换即使用，充值到用户虚拟账号中
			Date now = DateUtils.getDateShort(new Date());  //只取年月日
			
			//1. 插入或更新该兑换券的领取
			//添加一条领取记录（固定口令：到这里必定是需要插入的，前面已经判断了是否领过）
			try{
				if (detail==null){
					detail = new CashcardDetail();
				}
				detail.setCashcardId(info.getId());
				
				if(bInsert){  //插入时才用重新生成兑换券
					detail.setCashcardCode(generatorCashcardCodeBy(info.getId()));
					detail.setMakeTime(new Date());
				}

				detail.setUserId(userId);
				detail.setIsUsed(isUsed); //设为已使用
				detail.setUseTime(new Date());
				
				if(bInsert == true){
					cashcardDetailMapper.insertSelective(detail);
					logger.info("======== insertOrUpdateCashcardDetailBy insert===change_code="+detail.getCashcardCode() +" userId ="+userId);

				}else{
					cashcardDetailMapper.updateSelectiveById(detail);
					logger.info("======== insertOrUpdateCashcardDetailBy update====change_code="+detail.getCashcardCode() +" userId ="+userId);
				}
				
				//2.券的领取人数加1
				info.setGetedCount(info.getGetedCount() + 1);
				cashcardInfoMapper.updateSelectiveById(info);		
				
				//3. 增加 用户的余额 user_account(用户虚拟账户表）：
				BigDecimal sum = updateUserAccountRecord(userId, info.getCashcardAmt());
				
				//4. 插入充值记录表 user_account_recharge(充值记录表）
				insertUserAccountRechargeRecord(userId, 2, info.getCashcardAmt(), info.getCashcardAmt(), detail.getCashcardCode());

				//5.发送兑换成功的模板消息
				UserAccountRecharge userAccountRecharge = new UserAccountRecharge();
				userAccountRecharge.setRechargeType(2);  //1:微信支付，2:兑换码
				userAccountRecharge.setCreateTime(new Date());
				userAccountRecharge.setUserId(userId);
				userAccountRecharge.setActualAmt(info.getCashcardAmt());
				userAccountRecharge.setChangeCode(detail.getCashcardCode());
				templateSendService.sendCashCardRechargeSucc(userAccountRecharge);
				
				return Ret_ChangeType.Ret_Success;
				
			}catch(Exception e){
				e.printStackTrace();
				logger.error("insertOrUpdateCashcardDetailBy error: change_code="+detail!=null?detail.getCashcardCode():"null" +" userId ="+userId + " error log:" + e.getMessage());
				throw new RuntimeException();
			}
		}
		
		return Ret_ChangeType.Ret_InValid;
	}
	

	//------------------------------------------------------------------------
	//兑换 储值卡 码
	private Ret_ChangeType cashcardChange(String change_code, Integer userId, Map<String, Object> retMap,boolean onlyQuery) {
		logger.info("======== cashcardChange start ======================= parameter : change_code="+change_code +" userId ="+userId);
		
		if(StringUtils.isEmpty(change_code) || userId < 1){
			return Ret_ChangeType.Ret_Other;  
		}
		//先查询 储值卡表：cashcard_info 是否有该券 --固定的口令是在cashcard_info表
		CashcardInfo cashcardInfo = cashcardInfoMapper.selectByChangeCode(change_code);
		if (cashcardInfo == null){
			//如果主表查不到，一是随机产生的兑换券，查cashcard_detail表 
			CashcardDetail cashcardDetail = cashcardDetailMapper.selectByChangeCode(change_code);
			if(cashcardDetail == null){
				//cashcard_info和cashcard_detail表都查不到，则表示没有该兑换券
				return Ret_ChangeType.Ret_NotFound;
			}else{
				//一定是随机生成的兑换码。并且是已经在detail表里面有的，这里最多只用update状态		
				if(0 == cashcardDetail.getIsValid()){
					//该优惠券已失效
					return Ret_ChangeType.Ret_InValid;
				}else if(1 == cashcardDetail.getIsUsed()){
					//该券已使用
					return Ret_ChangeType.Ret_AlreadyChange;
				}else{
					//先查询coupon_info表，取兑换时间等参数比较
					cashcardInfo = cashcardInfoMapper.selectByPrimaryKey(cashcardDetail.getCashcardId());
					if(cashcardInfo == null){
						return Ret_ChangeType.Ret_NotFound; 
					}else if (cashcardInfo.getGetMode() == 1){ //到这里的话，mode必须是随机生成，这里强校验下。
						return Ret_ChangeType.Ret_NotFound;
					}else if(cashcardInfo.getIsOneVote().intValue() == 1){//isOneVote = 1 的时候 一个批次一个人只能兑换一次
						int countD = cashcardDetailMapper.queryCountByUserIdAndCashcardId(cashcardInfo.getId(), userId);
						if(countD > 0){
							return Ret_ChangeType.Ret_isOneVote;
						}
					}else if(cashcardInfo.getCashcardStatus().intValue() == CashcardConstants.CashcardStatus_del.intValue()){
						// 这里再次做一下校验 如果改储值卡已经被作废了
						return Ret_ChangeType.Ret_InValid;
					}
					if (retMap!= null){
						retMap.put("cashcard_name", cashcardInfo.getCashcardName());
						retMap.put("cashcard_amt", cashcardInfo.getCashcardAmt());
					}
					
					//插入一条优惠券
					return insertOrUpdateCashcardDetailBy(cashcardInfo, userId, cashcardDetail, false, retMap, onlyQuery);
				}
				
			}
			
		}else{
			//固定的口令，只在coupon_info表里有，Detail表里可能会有领取记录（有则表示添加过，没有则添加)
			CashcardDetail detail = cashcardDetailMapper.selectByCodeAndUserID(change_code, userId);
			// 表示该兑换码已经作废
			if(cashcardInfo.getCashcardStatus().intValue() != CashcardConstants.CashcardStatus_Online.intValue()){
				return Ret_ChangeType.Ret_InValid;
			}
			if (detail != null && detail.getCashcardId().intValue() == cashcardInfo.getId().intValue() && userId.intValue() == detail.getUserId().intValue()){//口令相同，并且批次相同， 则表示已经领取
				//该券已领取
				return Ret_ChangeType.Ret_AlreadyChange;
			}
				
			if (retMap!= null){
				retMap.put("cashcard_name", cashcardInfo.getCashcardName());
				retMap.put("cashcard_amt", cashcardInfo.getCashcardAmt());
			}
			
			//插入一条优惠券
			return insertOrUpdateCashcardDetailBy(cashcardInfo, userId, detail, true, retMap,onlyQuery);
		}	
	}
	
	/**
	 * 兑换 储值卡
	 */
	@Override
	public ApiResultModel cashcardChange(Map<String, Object> paramsMap) {
		ApiResultModel model = new ApiResultModel();
		
		String userId = paramsMap.get("user_id").toString();
		String code = paramsMap.get("cashcard_code").toString();
		if(StringUtils.isEmpty(userId) || StringUtils.isEmpty(code)){
			model.setMsg(Ret_ChangeType.Ret_Other.getValue());
			model.setRet(Ret_ChangeType.Ret_Other.getIndex());
			return model;
		}
		
		Map<String, Object> retMap = new HashMap<String, Object>();//返回的参数
		
		//是否仅查询
		boolean onlyQuery = paramsMap.get("onlyQuery") !=null && paramsMap.get("onlyQuery").toString().equals("1") ? true:false;

		Ret_ChangeType retType = cashcardChange(code, Integer.valueOf(userId), retMap, onlyQuery);
	
		if (retType== Ret_ChangeType.Ret_Success){		
			model.setData(retMap);
			
			// 用户充值记录插入
			UserAccountRecharge uar = userAccountRechargeMapper.queryUserAccountRecharge(userId,  code);
			logger.info("=========cashcardChange ==params：userId:"+userId+" code:"+code+"=====================");
			if(uar!=null){
				templateSendService.sendCashCardRechargeSucc(uar);
			}

		}

		model.setRet(retType.getIndex());
		model.setErrorCode(retType.getIndex());
		if(retType == Ret_ChangeType.Ret_BeforeTime && retMap.get("change_begin_date")!=null){
			model.setMsg("温馨提示：该券的兑换时间还没到，兑换开始时间为：" + retMap.get("change_begin_date"));
		}else if(retType == Ret_ChangeType.Ret_ExpiredTime && retMap.get("change_end_date")!=null){
			model.setMsg("温馨提示：该券的兑换时间已过，兑换结束时间为：" + retMap.get("change_end_date"));
		}else{
			model.setMsg(retType.getValue());
		}

		return model;
	}

	

	/**
	 * @see //按照批次信息生成兑换码,如果获取方式是1：用户输入码，则直接使用cashcardInfo里面的兑换码；
	 * @see //如果兑换方式为2：系统自动生成：兑换码==4位批次+12位不重复的字符串组合。保证唯一性。
	 * @param cashcardId 兑换券批次ID
	 * @return String cashcardCode 兑换码
	 */
	public String generatorCashcardCodeBy(Integer cashcardId) {
		CashcardInfo info = cashcardInfoMapper.selectByPrimaryKey(cashcardId);
		if (info != null) {
			// 如果获取方式是用户输入兑换码领取，表示兑换码已固定，否则则生成兑换码
			if (1 == info.getGetMode().intValue()) {
				return info.getCashcardCode();
			} else {
				String code = null;
				// 从数据库查询出是否存在兑换码，如果有则从新生成。
				while (true) {
					code = CouponUtil.generatorCoupinCode(cashcardId);
					CashcardDetail detail = cashcardDetailMapper.selectByChangeCode(code);
					if (detail == null) {
						break;
					}
				}
				return code;
			}
		} else {
			return null;
		}
	}
	
	/**
	 * 查询用户可以充值的面额，这里的城市id先写死给的是深圳市的
	 */
	@Override
	public ApiResultModel getUserRechargeDiscountList(int userId, int cityId) {
		ApiResultModel apiResultModel = new ApiResultModel();
		DecimalFormat df=new DecimalFormat("000000");
		Map<String,Object> map = new HashMap<>();
		UserInfo userInfo = userInfoMapper.selectById(userId);
		map.put("accountAmt", userInfo.getAccountAmt());
		String userAccountNo = df.format(userInfo.getId());
		map.put("userAccountNO", userAccountNo);
		map.put("level", userInfo.getLevel());
		List<RechargeDiscount> list = rechargeDiscountService.queryRechargeDiscountByCity(199);
		map.put("recharge", list);
		map.put("orderType",OrderContants.OrderType.user_account.getIndex());
		apiResultModel.setData(map);
		apiResultModel.setRet(0);
		apiResultModel.setErrorCode(0);
		apiResultModel.setLogined(true);
		return apiResultModel;
	}
	
	
	/**
	 * 根据优惠券批次ID 查询优惠券兑换码
	 */
	@Override
	public ApiResultModel queryCardNoByCardId(Integer cardId) {
		ApiResultModel model = new ApiResultModel();
		if (cardId > 0) {
			CashcardDetail cashcardDetail = cashcardDetailMapper.selectCardNoByid(cardId);
			if (cashcardDetail != null) {
				model.setData(cashcardDetail);
				model.setRet(ApiResultModel.RET_SUCCESS);
			} else {
				model.setRet(ApiResultModel.RET_SUCCESS);
				model.setMsg("该批次的充值卡已兑换完");
			}
		} else {
			model.setRet(ApiResultModel.RET_ERROR);
			model.setMsg("未传入正确参数");
		}
		return model;
	}

	@Override
	public ApiResultModel getUserYearCardConsumeLog(Map<String,Object> parmaMap) {
		ApiResultModel<Object> model = new ApiResultModel<>();
		Map<String,Object> resultMap = new HashMap<>();
		Integer pageIndex = (Integer) parmaMap.get("pageIndex");
		Integer pageSize = (Integer) parmaMap.get("pageSize");
		Page<YearCardConvertDateOrderLog> page = new Page<>(pageIndex, pageSize);
		List<YearCardConvertDateOrderLog> list = orderInfoMapper.queryUserYearCardConsumeLog(page, parmaMap);
		page.setRecords(list);
		resultMap.put("userAccountYearCardConsumeCount", page.getTotal());
		resultMap.put("userAccountYearCardConsumePage", page.getRecords());
		resultMap.put("pages", page.getPages());
		model.setData(resultMap);
		model.setRet(ApiResultModel.RET_SUCCESS);
		return model;
	}
	
}
